﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace CWM.Skinn
{
    public static partial class SkinnContext
    {
        public static class MenuMain
        {
            public static bool ContextShown { get; set; }

            public static void ContextGUI(int id, Rect selectionRect)
            {
                if (ContextShown || InstanceIDs.Count < 1) return;
                ContextShown = true;
                ShowContextMenu();
            }

            public static void ShowContextMenu()
            {
                GenericMenu menu = new GenericMenu();
                menu.AddDisabledItem(new GUIContent(ContextType));
                menu.AddSeparator("");
                menu.AddItem(new GUIContent("Cancel"), false, ContextMenuSelected, "Cancel");
                menu.AddSeparator("");
                var methods = typeof(SkinnContextCommands).GetMethods();
                List<CtxMenuItem> ctxItems = new List<CtxMenuItem>();
                foreach (var method in methods)
                {
                    var attributes = method.GetCustomAttributes(true);
                    for (int i = 0; i < attributes.Length; i++)
                    {
                        var ctxItem = attributes[i] as CtxMenuItem; if (!ctxItem) continue;
                        var ctxType = ctxItem.menuItem.Remove(ctxItem.menuItem.IndexOf("/"));
                        if (ctxType == ContextID.Renderer)
                        {
                            if (ContextType == ContextID.MeshRenderer) ctxType = ContextType;
                            else if (ContextType == ContextID.SkinnedMeshRenderer) ctxType = ContextType;
                        }
                        if (ctxType != ContextType) continue;
                        ctxItems.Add(ctxItem);
                        break;
                    }
                }

                var allBones = ContextUtility.GetAllBones();
                var allShapes = ContextUtility.GetAllBlendshapes();

                if (SkinnInternalAsset.DevLog)
                {
                    Debug.LogWarning("DevLog enable ContextRequirements skipped!");
                }


                for (int i = 0; i < ctxItems.Count; i++)
                {
                    var ctxItem = ctxItems[i];
                    if (string.IsNullOrEmpty(ctxItem.menuItem)) continue;
                    var label = ContextID.Label(ctxItem.menuItem);
                    if (ctxItem.flags == ContextFlag.Header)
                    {
                        menu.AddDisabledItem(new GUIContent(label));
                        continue;
                    }

                    if (!ContextUtility.HasRequirements(ctxItem.requirements) && !SkinnInternalAsset.DevLog)
                    {
                        menu.AddDisabledItem(new GUIContent(label));
                    }
                    else if (ctxItem.flags == ContextFlag.PasteFunction && !CopyRef.Asset)
                        menu.AddDisabledItem(new GUIContent(label));
                    else if (ctxItem.flags == ContextFlag.Bone || ctxItem.flags == ContextFlag.BoneWithChildern)
                    {
                        foreach (var itemX in allBones)
                        {
                            if (ctxItem.flags == ContextFlag.BoneWithChildern && !itemX.Value.hasChildInArray) continue;

                            var id = ctxItem.menuItem + ContextID.BoneSubKey + itemX.Key;
                            var subLabel = label + "/" + itemX.Value.name;
                            menu.AddItem(new GUIContent(subLabel), false, ContextMenuSelected, id);
                        }
                    }
                    else if (ctxItem.flags == ContextFlag.BoneBone)
                    {
                        foreach (var itemX in allBones)
                        {
                            var id = ctxItem.menuItem + ContextID.BoneSubKey + itemX.Key + ContextID.BoneSubKey;
                            var subLabel = label + "/" + itemX.Value.name;
                            menu.AddItem(new GUIContent(subLabel), false, ContextMenuSelected, id);
                        }
                    }
                    else if (ctxItem.flags == ContextFlag.Blendshape)
                    {
                        foreach (var itemX in allShapes)
                        {
                            var id = ctxItem.menuItem + ContextID.BlendshapeSubKey + itemX;
                            var subLabel = label + "/" + itemX;
                            menu.AddItem(new GUIContent(subLabel), false, ContextMenuSelected, id);
                        }
                    }
                    else if (ctxItem.flags == ContextFlag.BlendshapeBlendshape)
                    {
                        foreach (var itemX in allShapes)
                        {
                            var id = ctxItem.menuItem + ContextID.BlendshapeSubKey + itemX + ContextID.BlendshapeSubKey;
                            var subLabel = label + "/" + itemX;
                            menu.AddItem(new GUIContent(subLabel), false, ContextMenuSelected, id);
                        }
                    }
                    else
                        menu.AddItem(new GUIContent(label), false, ContextMenuSelected, ctxItem.menuItem);
                }

                if (ContextType == ContextID.SkinnedMeshRenderer || ContextType == ContextID.MeshRenderer)
                {
                    foreach (var item in SkinnInternalAsset.GetUnlitMaterials)
                    {
                        if (!item) continue; var contextPath = "Material/Internal/" + item.name;
                        menu.AddItem(new GUIContent(contextPath), false, ContextMenuSelected, item);
                    }

                    foreach (var item in SkinnInternalAsset.GetStandardMaterials)
                    {
                        if (!item) continue; var contextPath = "Material/Standard/" + item.name;
                        menu.AddItem(new GUIContent(contextPath), false, ContextMenuSelected, item);
                    }
                }

                menu.ShowAsContext();

                var window = SkinnEditorEx.GetSceneViewWindow;
                if (window) window.wantsMouseMove = true;
            }

            private static void ContextMenuSelected(object id)
            {
                ContextBone0 = -1;
                ContextShape0 = "";

                var material = id as Material;
                if (material)
                {
                    ContextUtility.ApplyMaterial(material);
                    ContextShown = false; Finished(); return;
                }

                var methodID = id as string;
                if (methodID.Contains(ContextID.BoneSubKey))
                {
                    methodID = methodID.Replace(ContextID.BoneSubKey, "*");
                    var subKey = methodID.Split('*');
                    methodID = subKey[0];
                    int key0; try { key0 = System.Convert.ToInt32(subKey[1]); } catch { key0 = -1; Debug.LogError(subKey[0] + " " + subKey[1]); }

                    ContextBone0 = key0;

                    if (subKey.Length > 2)
                    {
                        MenuBones.MethodID = methodID;
                        MenuBones.ContextShown = false;
                        return;
                    }
                }


                if (methodID.Contains(ContextID.BlendshapeSubKey))
                {
                    methodID = methodID.Replace(ContextID.BlendshapeSubKey, "*");
                    var subKey = methodID.Split('*');
                    methodID = subKey[0];
              
                    ContextShape0 = subKey[1];

                    if (subKey.Length > 2)
                    {
                        MenuShapes.MethodID = methodID;
                        MenuShapes.ContextShown = false;
                        return;
                    }
                }

                InvokeContext(methodID);
                ContextShown = false;
            }
        }
    }
}
